package com.zmn.oms.services.config;

import com.google.common.collect.Lists;
import com.zmn.oms.persistence.algorithm.HashModuloShardingTableAlgorithm;
import io.shardingsphere.api.algorithm.masterslave.RoundRobinMasterSlaveLoadBalanceAlgorithm;
import io.shardingsphere.api.config.rule.MasterSlaveRuleConfiguration;
import io.shardingsphere.api.config.rule.ShardingRuleConfiguration;
import io.shardingsphere.api.config.rule.TableRuleConfiguration;
import io.shardingsphere.api.config.strategy.NoneShardingStrategyConfiguration;
import io.shardingsphere.api.config.strategy.StandardShardingStrategyConfiguration;
import io.shardingsphere.core.constant.properties.ShardingPropertiesConstant;
import io.shardingsphere.core.keygen.DefaultKeyGenerator;
import io.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;

/**
* sharding-jdbc & mybatis 配置
* @author LuJia
* @version v1.0
* @since 2020/6/27 15:50
**/
@Slf4j
@Configuration
@MapperScan(basePackages = "com.zmn.oms.persistence.interfaces",
        sqlSessionTemplateRef = "shardingSqlSessionTemplate",
        sqlSessionFactoryRef = "shardingSqlSessionFactory")
public class ShardingMybatisConfig implements ApplicationContextAware {

    /**
     * 是否开启sql显示,默认false
     */
    @Value("${spring.datasource.sql.show:false}")
    private String showSql;

    /**
     * 主从库 数据源名称
     */
    private static final String masterName = "masterDataSource";
    private static final List<String> slaveNames = Lists.newArrayList("slaveDataSource0");

    private ApplicationContext applicationContext;

    /**
     * mybatis 配置
     */
    private static final String MAPPERS_LOCATION = "classpath:mapper/**/*.xml";
    private static final String CONFIG_LOCATION = "classpath:common/oms-mybatis.xml";

    /**
     * 初始化主键生成器
     * @return
     */
    @Bean
    public DefaultKeyGenerator createDefaultKeyGenerator() {
        return new DefaultKeyGenerator();
    }

    /**
     * 初始化分表规则
     * @param configurations
     */
    private void addTableRules(Collection<TableRuleConfiguration> configurations) {

        // 分片规则
        configurations.add(getOmsOrderTableRuleConfiguration());
        configurations.add(getOmsOrderCommentTableRuleConfiguration());
        configurations.add(getOmsOrderCommentDetailTableRuleConfiguration());
        configurations.add(getOmsOrderRemarkTableRuleConfiguration());
        configurations.add(getOmsOrderRemarkDetailTableRuleConfiguration());
        configurations.add(getOmsOrderDetailTableRuleConfiguration());
        configurations.add(getOmsOrderDiscountTableRuleConfiguration());
        configurations.add(getOmsOrderInvoiceTableRuleConfiguration());
        configurations.add(getOmsOrderMasterTableRuleConfiguration());
        configurations.add(getOmsOrderMemberTableRuleConfiguration());
        configurations.add(getOmsOrderFactoryTableRuleConfiguration());
        configurations.add(getOmsOrderPartTableRuleConfiguration());
        configurations.add(getOmsOrderProductTableRuleConfiguration());
        configurations.add(getOmsOrderProductExtendTableRuleConfiguration());
        configurations.add(getOmsOrderReplyTableRuleConfiguration());
        configurations.add(getOmsOrderReplyDetailTableRuleConfiguration());
        configurations.add(getOmsOrderServiceItemTableRuleConfiguration());
        configurations.add(getOmsOrderServiceItemDetailTableRuleConfiguration());
        configurations.add(getOmsOrderTrackTableRuleConfiguration());
        configurations.add(getOmsOrderWarrantyTableRuleConfiguration());
        configurations.add(getOmsOrderWarrantyProductTableRuleConfiguration());
        configurations.add(getOmsOrderWorkTableRuleConfiguration());
        configurations.add(getOmsOrderExtendTableRuleConfiguration());
        configurations.add(getOmsOrderWorkRefundTableRuleConfiguration());
        configurations.add(getOmsOrderShopTableRuleConfiguration());
        configurations.add(getOmsOrderChangeRecordTableRuleConfiguration());
        configurations.add(getOmsOrderWorkStatementTableRuleConfiguration());
        configurations.add(getOmsOrderOperationTableRuleConfiguration());
        configurations.add(getOmsOrderCallRecordTableRuleConfiguration());
        configurations.add(getOmsOrderNonstandardTableRuleConfiguration());
        configurations.add(getOmsOrderPositionTableRuleConfiguration());
        configurations.add(getOmsOrderAttachmentTableRuleConfiguration());
        configurations.add(getOmsOrderThirdAppBindTableRuleConfiguration());
        configurations.add(getOmsOrderVisitTableRuleConfiguration());
        configurations.add(getOmsOrderPayTableRuleConfiguration());
        configurations.add(getOmsOrderWorkTrackTableRuleConfiguration());
        configurations.add(getOmsOrderTagTableRuleConfiguration());
        configurations.add(getOmsOrderReviewTableRuleConfiguration());
        configurations.add(getOmsOrderCompensateTableRuleConfiguration());
        configurations.add(getOmsOrderActivityTableRuleConfiguration());
        configurations.add(getOmsOrderWorkOperatorTableRuleConfiguration());
        configurations.add(getOmsOrderWorkAcceptanceTableRuleConfiguration());
        configurations.add(getOrderWorkRefundDetailTableRuleConfiguration());
        configurations.add(getOrderQuotationProcessTableRuleConfiguration());
        configurations.add(getOrderFaultTableRuleConfiguration());
        configurations.add(getOrderFaultPhenomenonTableRuleConfiguration());
        configurations.add(getOrderMaintainItemTableRuleConfiguration());
        configurations.add(getOrderQuotationServiceItemTableRuleConfiguration());
        configurations.add(getOrderServiceContentTableRuleConfiguration());
        configurations.add(getOrderAcceptMaintainItemTableRuleConfiguration());
        configurations.add(getOrderPreDistributeRecordTableRuleConfiguration());
        configurations.add(getOmsOrderWorkRelationTableRuleConfiguration());
        configurations.add(getOrderPartAdditionTableRuleConfiguration());
        configurations.add(getOrderServiceItemCellTableRuleConfiguration());
        configurations.add(getFindPriceOrderExtTableRuleConfiguration());
        configurations.add(getOmsOrderWorkingRecordTableRuleConfiguration());
        configurations.add(getOmsOrderEnterpriseWechatLogConfiguration());
        configurations.add(getOmsOrderFinalPriceQuotationTableRuleConfiguration());
    }

    /**
     * 添加绑定表
     * 相同分表规则下使用
     * 避免连表时造成笛卡尔积
     * @param configurations
     */
    private void addBindingTables(Collection<String> configurations) {
        configurations.add("oms_order_work,oms_order_service_item");
        configurations.add("oms_order_extend,oms_order_work");
    }

    /**
     * 初始化sharding 数据源
     * @return
     * @throws SQLException
     */
    @Bean
    public DataSource shardingDataSource() throws SQLException {

        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();

        // 分片规则
        addTableRules(shardingRuleConfig.getTableRuleConfigs());

        // 主表 字表绑定
        addBindingTables(shardingRuleConfig.getBindingTableGroups());

        // 分库策略：不分库只分表
        shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new NoneShardingStrategyConfiguration());
        // 分表策略：默认不分表
        shardingRuleConfig.setDefaultTableShardingStrategyConfig(new NoneShardingStrategyConfiguration());

        // 读写分离规则
        shardingRuleConfig.setMasterSlaveRuleConfigs(getMasterSlaveRuleConfigurations());

        // 默认自增列值生成器
        shardingRuleConfig.setDefaultKeyGenerator(new DefaultKeyGenerator());

        // sharding sql显示配置
        Properties props = new Properties();
        props.put(ShardingPropertiesConstant.SQL_SHOW.getKey(), showSql);

        return ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfig, new HashMap<String, Object>(2), props);
    }

    TableRuleConfiguration getOmsOrderWorkRefundTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_work_refund");
        result.setActualDataNodes("ds_0.oms_order_work_refund_${0..7}");
        result.setKeyGeneratorColumnName("refund_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderShopTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_shop");
        result.setActualDataNodes("ds_0.oms_order_shop_${0..7}");
        result.setKeyGeneratorColumnName("shop_order_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("shop_order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order");
        result.setActualDataNodes("ds_0.oms_order_${0..7}");
        result.setKeyGeneratorColumnName("order_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderWorkTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_work");
        result.setActualDataNodes("ds_0.oms_order_work_${0..7}");
        result.setKeyGeneratorColumnName("work_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderCommentTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_comment");
        result.setActualDataNodes("ds_0.oms_order_comment_${0..7}");
        result.setKeyGeneratorColumnName("comment_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("comment_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderCommentDetailTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_comment_detail");
        result.setActualDataNodes("ds_0.oms_order_comment_detail_${0..7}");
        result.setKeyGeneratorColumnName("detail_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("comment_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderRemarkTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_remark");
        result.setActualDataNodes("ds_0.oms_order_remark_${0..7}");
        result.setKeyGeneratorColumnName("remark_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderRemarkDetailTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_remark_detail");
        result.setActualDataNodes("ds_0.oms_order_remark_detail_${0..7}");
        result.setKeyGeneratorColumnName("remark_detail_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderDetailTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_detail");
        result.setActualDataNodes("ds_0.oms_order_detail_${0..7}");
        result.setKeyGeneratorColumnName("detail_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("detail_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderChangeRecordTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_change_record");
        result.setActualDataNodes("ds_0.oms_order_change_record_${0..7}");
        result.setKeyGeneratorColumnName("order_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderWorkStatementTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_work_statement");
        result.setActualDataNodes("ds_0.oms_order_work_statement_${0..7}");
        result.setKeyGeneratorColumnName("order_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderDiscountTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_discount");
        result.setActualDataNodes("ds_0.oms_order_discount_${0..7}");
        result.setKeyGeneratorColumnName("discount_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderInvoiceTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_invoice");
        result.setActualDataNodes("ds_0.oms_order_invoice_${0..7}");
        result.setKeyGeneratorColumnName("invoice_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("invoice_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderMasterTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_work_master");
        result.setActualDataNodes("ds_0.oms_order_work_master_${0..7}");
        result.setKeyGeneratorColumnName("master_order_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderMemberTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_member");
        result.setActualDataNodes("ds_0.oms_order_member_${0..7}");
        result.setKeyGeneratorColumnName("member_order_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("member_order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderFactoryTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_factory");
        result.setActualDataNodes("ds_0.oms_order_factory_${0..7}");
        result.setKeyGeneratorColumnName("fc_order_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("fc_order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderPartTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_part");
        result.setActualDataNodes("ds_0.oms_order_part_${0..7}");
        result.setKeyGeneratorColumnName("order_part_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderProductTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_product");
        result.setActualDataNodes("ds_0.oms_order_product_${0..7}");
        result.setKeyGeneratorColumnName("pro_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderProductExtendTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_product_extend");
        result.setActualDataNodes("ds_0.oms_order_product_extend_${0..7}");
        result.setKeyGeneratorColumnName("pro_ext_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderReplyTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_reply");
        result.setActualDataNodes("ds_0.oms_order_reply_${0..7}");
        result.setKeyGeneratorColumnName("reply_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("reply_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderReplyDetailTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_reply_detail");
        result.setActualDataNodes("ds_0.oms_order_reply_detail_${0..7}");
        result.setKeyGeneratorColumnName("reply_detail_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("reply_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderServiceItemTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_service_item");
        result.setActualDataNodes("ds_0.oms_order_service_item_${0..7}");
        result.setKeyGeneratorColumnName("item_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderServiceItemDetailTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_service_item_detail");
        result.setActualDataNodes("ds_0.oms_order_service_item_detail_${0..7}");
        result.setKeyGeneratorColumnName("detail_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderTrackTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_track");
        result.setActualDataNodes("ds_0.oms_order_track_${0..7}");
        result.setKeyGeneratorColumnName("track_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderWarrantyTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_warranty");
        result.setActualDataNodes("ds_0.oms_order_warranty_${0..7}");
        result.setKeyGeneratorColumnName("warr_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("warr_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderWarrantyProductTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_warranty_product");
        result.setActualDataNodes("ds_0.oms_order_warranty_product_${0..7}");
        result.setKeyGeneratorColumnName("pro_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("warr_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderExtendTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_extend");
        result.setActualDataNodes("ds_0.oms_order_extend_${0..7}");
        result.setKeyGeneratorColumnName("ext_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("ext_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderOperationTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_operation");
        result.setActualDataNodes("ds_0.oms_order_operation_${0..7}");
        result.setKeyGeneratorColumnName("order_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderNonstandardTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_nonstandard");
        result.setActualDataNodes("ds_0.oms_order_nonstandard_${0..7}");
        result.setKeyGeneratorColumnName("order_nonstandard_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderPositionTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_position");
        result.setActualDataNodes("ds_0.oms_order_position_${0..7}");
        result.setKeyGeneratorColumnName("position_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("position_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderCallRecordTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_call_record");
        result.setActualDataNodes("ds_0.oms_order_call_record_${0..7}");
        result.setKeyGeneratorColumnName("call_record_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderAttachmentTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_attachment");
        result.setActualDataNodes("ds_0.oms_order_attachment_${0..7}");
        result.setKeyGeneratorColumnName("attachment_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderThirdAppBindTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_thirdapp_bind");
        result.setActualDataNodes("ds_0.oms_order_thirdapp_bind_${0..7}");
        result.setKeyGeneratorColumnName("bind_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderVisitTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_work_visit");
        result.setActualDataNodes("ds_0.oms_order_work_visit_${0..7}");
        result.setKeyGeneratorColumnName("visit_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderPayTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_pay");
        result.setActualDataNodes("ds_0.oms_order_pay_${0..7}");
        result.setKeyGeneratorColumnName("order_pay_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderTagTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_tag");
        result.setActualDataNodes("ds_0.oms_order_tag_${0..7}");
        result.setKeyGeneratorColumnName("order_tag_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderWorkTrackTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_work_track");
        result.setActualDataNodes("ds_0.oms_order_work_track_${0..7}");
        result.setKeyGeneratorColumnName("track_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderReviewTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_review");
        result.setActualDataNodes("ds_0.oms_order_review_${0..7}");
        result.setKeyGeneratorColumnName("review_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderCompensateTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_compensate");
        result.setActualDataNodes("ds_0.oms_order_compensate_${0..7}");
        result.setKeyGeneratorColumnName("compensate_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOrderWorkRefundDetailTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_work_refund_detail");
        result.setActualDataNodes("ds_0.oms_order_work_refund_detail_${0..7}");
        result.setKeyGeneratorColumnName("refund_detail_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOrderPreDistributeRecordTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_pre_distribute_record");
        result.setActualDataNodes("ds_0.oms_order_pre_distribute_record_${0..7}");
        result.setKeyGeneratorColumnName("pre_distribute_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOrderServiceItemCellTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_service_item_cell");
        result.setActualDataNodes("ds_0.oms_order_service_item_cell_${0..7}");
        result.setKeyGeneratorColumnName("cell_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getFindPriceOrderExtTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_final_price");
        result.setActualDataNodes("ds_0.oms_order_final_price_${0..7}");
        result.setKeyGeneratorColumnName("final_price_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOrderPartAdditionTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_part_addition");
        result.setActualDataNodes("ds_0.oms_order_part_addition_${0..7}");
        result.setKeyGeneratorColumnName("work_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderWorkOperatorTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_work_operator");
        result.setActualDataNodes("ds_0.oms_order_work_operator_${0..7}");
        result.setKeyGeneratorColumnName("work_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderActivityTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_activity");
        result.setActualDataNodes("ds_0.oms_order_activity_${0..7}");
        result.setKeyGeneratorColumnName("order_activity_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderWorkAcceptanceTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_work_acceptance");
        result.setActualDataNodes("ds_0.oms_order_work_acceptance_${0..7}");
        result.setKeyGeneratorColumnName("acceptance_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOrderQuotationProcessTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("order_quotation_process");
        result.setActualDataNodes("ds_0.order_quotation_process_${0..7}");
        result.setKeyGeneratorColumnName("quotation_process_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOrderFaultTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("order_fault");
        result.setActualDataNodes("ds_0.order_fault_${0..7}");
        result.setKeyGeneratorColumnName("order_fault_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }


    TableRuleConfiguration getOrderFaultPhenomenonTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("order_fault_phenomenon");
        result.setActualDataNodes("ds_0.order_fault_phenomenon_${0..7}");
        result.setKeyGeneratorColumnName("order_phenomenon_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }


    TableRuleConfiguration getOrderMaintainItemTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("order_maintain_item");
        result.setActualDataNodes("ds_0.order_maintain_item_${0..7}");
        result.setKeyGeneratorColumnName("order_maintain_item_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOrderQuotationServiceItemTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("order_quotation_service_item");
        result.setActualDataNodes("ds_0.order_quotation_service_item_${0..7}");
        result.setKeyGeneratorColumnName("service_item_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOrderServiceContentTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("order_service_content");
        result.setActualDataNodes("ds_0.order_service_content_${0..7}");
        result.setKeyGeneratorColumnName("order_service_content_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOrderAcceptMaintainItemTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("order_accept_maintain_item");
        result.setActualDataNodes("ds_0.order_accept_maintain_item_${0..7}");
        result.setKeyGeneratorColumnName("accept_maintain_item_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderWorkRelationTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_work_relation");
        result.setActualDataNodes("ds_0.oms_order_work_relation_${0..7}");
        result.setKeyGeneratorColumnName("relation_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderWorkingRecordTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_working_record");
        result.setActualDataNodes("ds_0.oms_order_working_record_${0..7}");
        result.setKeyGeneratorColumnName("record_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }
    TableRuleConfiguration getOmsOrderEnterpriseWechatLogConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_wechat_work_log");
        result.setActualDataNodes("ds_0.oms_order_wechat_work_log_${0..7}");
        result.setKeyGeneratorColumnName("enterprise_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }

    TableRuleConfiguration getOmsOrderFinalPriceQuotationTableRuleConfiguration() {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("oms_order_final_price_quotation");
        result.setActualDataNodes("ds_0.oms_order_final_price_quotation_${0..7}");
        result.setKeyGeneratorColumnName("final_price_id");
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new HashModuloShardingTableAlgorithm()));
        return result;
    }


    /**
     * 获取数据源map
     * 一主多从
     * @return
     */
    private Map<String, DataSource> createDataSourceMap() {
        final Map<String, DataSource> result = new HashMap<>(2);
        result.put(masterName, (DataSource) applicationContext.getBean(masterName));
        for (String str : slaveNames) {
            result.put(str, (DataSource) applicationContext.getBean(str));
        }
        return result;
    }

    /**
     * 主从分离配置
     * @return
     * @throws SQLException
     */
    private List<MasterSlaveRuleConfiguration> getMasterSlaveRuleConfigurations() {
        MasterSlaveRuleConfiguration masterSlaveRuleConfig = new MasterSlaveRuleConfiguration();
        masterSlaveRuleConfig.setName("ds_0");
        masterSlaveRuleConfig.setMasterDataSourceName(masterName);
        masterSlaveRuleConfig.setSlaveDataSourceNames(slaveNames);
        masterSlaveRuleConfig.setLoadBalanceAlgorithm(new RoundRobinMasterSlaveLoadBalanceAlgorithm());
        return Lists.newArrayList(masterSlaveRuleConfig);
    }

    @Bean
    public SqlSessionFactory shardingSqlSessionFactory(@Qualifier("shardingDataSource") DataSource shardingDataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        VFS.addImplClass(SpringBootVFS.class);
        bean.setConfigLocation(new PathMatchingResourcePatternResolver().getResource(CONFIG_LOCATION));
        bean.setDataSource(shardingDataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPERS_LOCATION));
        return bean.getObject();
    }

    @Bean
    public DataSourceTransactionManager shardingTransactionManager(@Qualifier("shardingDataSource") DataSource shardingDataSource) {
        return new DataSourceTransactionManager(shardingDataSource);
    }

    @Bean
    public SqlSessionTemplate shardingSqlSessionTemplate(@Qualifier("shardingSqlSessionFactory") SqlSessionFactory shardingSqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(shardingSqlSessionFactory);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
